/**
 * 验证工具函数
 * @author Wu.Liang
 * @date 2025-01-21
 */

/**
 * 验证手机号
 * @param {string} phone 手机号
 * @returns {boolean}
 */
export const validatePhone = (phone) => {
  if (!phone) return false
  const phoneRegex = /^1[3-9]\d{9}$/
  return phoneRegex.test(String(phone))
}

/**
 * 验证邮箱
 * @param {string} email 邮箱
 * @returns {boolean}
 */
export const validateEmail = (email) => {
  if (!email) return false
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  return emailRegex.test(String(email))
}

/**
 * 验证身份证号
 * @param {string} idCard 身份证号
 * @returns {boolean}
 */
export const validateIdCard = (idCard) => {
  if (!idCard) return false
  
  const idCardStr = String(idCard).replace(/\D/g, '')
  if (idCardStr.length !== 18) return false
  
  // 验证出生日期
  const year = parseInt(idCardStr.substring(6, 10))
  const month = parseInt(idCardStr.substring(10, 12))
  const day = parseInt(idCardStr.substring(12, 14))
  
  const date = new Date(year, month - 1, day)
  if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {
    return false
  }
  
  // 验证校验码
  const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
  const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
  
  let sum = 0
  for (let i = 0; i < 17; i++) {
    sum += parseInt(idCardStr[i]) * weights[i]
  }
  
  const checkCode = checkCodes[sum % 11]
  return idCardStr[17] === checkCode
}

/**
 * 验证密码强度
 * @param {string} password 密码
 * @returns {object} 包含强度等级和建议
 */
export const validatePassword = (password) => {
  if (!password) {
    return {
      isValid: false,
      strength: 0,
      suggestions: ['密码不能为空']
    }
  }
  
  const suggestions = []
  let strength = 0
  
  // 长度检查
  if (password.length < 8) {
    suggestions.push('密码长度至少8位')
  } else {
    strength += 1
  }
  
  // 包含数字
  if (/\d/.test(password)) {
    strength += 1
  } else {
    suggestions.push('密码应包含数字')
  }
  
  // 包含小写字母
  if (/[a-z]/.test(password)) {
    strength += 1
  } else {
    suggestions.push('密码应包含小写字母')
  }
  
  // 包含大写字母
  if (/[A-Z]/.test(password)) {
    strength += 1
  } else {
    suggestions.push('密码应包含大写字母')
  }
  
  // 包含特殊字符
  if (/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password)) {
    strength += 1
  } else {
    suggestions.push('密码应包含特殊字符')
  }
  
  return {
    isValid: strength >= 3,
    strength: strength,
    suggestions: suggestions
  }
}

/**
 * 验证用户名
 * @param {string} username 用户名
 * @returns {boolean}
 */
export const validateUsername = (username) => {
  if (!username) return false
  
  // 用户名规则：4-20位，只能包含字母、数字、下划线
  const usernameRegex = /^[a-zA-Z0-9_]{4,20}$/
  return usernameRegex.test(String(username))
}

/**
 * 验证验证码
 * @param {string} captcha 验证码
 * @param {number} length 验证码长度
 * @returns {boolean}
 */
export const validateCaptcha = (captcha, length = 4) => {
  if (!captcha) return false
  
  const captchaRegex = new RegExp(`^\\d{${length}}$`)
  return captchaRegex.test(String(captcha))
}

/**
 * 验证短信验证码
 * @param {string} smsCode 短信验证码
 * @returns {boolean}
 */
export const validateSmsCode = (smsCode) => {
  return validateCaptcha(smsCode, 6)
}

/**
 * 验证银行卡号
 * @param {string} cardNumber 银行卡号
 * @returns {boolean}
 */
export const validateBankCard = (cardNumber) => {
  if (!cardNumber) return false
  
  const cardStr = String(cardNumber).replace(/\D/g, '')
  if (cardStr.length < 13 || cardStr.length > 19) return false
  
  // Luhn算法验证
  let sum = 0
  let isEven = false
  
  for (let i = cardStr.length - 1; i >= 0; i--) {
    let digit = parseInt(cardStr[i])
    
    if (isEven) {
      digit *= 2
      if (digit > 9) {
        digit -= 9
      }
    }
    
    sum += digit
    isEven = !isEven
  }
  
  return sum % 10 === 0
}

/**
 * 验证URL
 * @param {string} url URL地址
 * @returns {boolean}
 */
export const validateUrl = (url) => {
  if (!url) return false
  
  try {
    new URL(url)
    return true
  } catch {
    return false
  }
}

/**
 * 验证IP地址
 * @param {string} ip IP地址
 * @returns {boolean}
 */
export const validateIp = (ip) => {
  if (!ip) return false
  
  const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
  return ipRegex.test(String(ip))
}

/**
 * 验证端口号
 * @param {string|number} port 端口号
 * @returns {boolean}
 */
export const validatePort = (port) => {
  if (!port) return false
  
  const portNum = parseInt(port)
  return portNum >= 1 && portNum <= 65535
}

/**
 * 验证文件大小
 * @param {number} size 文件大小（字节）
 * @param {number} maxSize 最大文件大小（字节）
 * @returns {boolean}
 */
export const validateFileSize = (size, maxSize) => {
  if (!size || !maxSize) return false
  return size <= maxSize
}

/**
 * 验证文件类型
 * @param {string} fileName 文件名
 * @param {array} allowedTypes 允许的文件类型
 * @returns {boolean}
 */
export const validateFileType = (fileName, allowedTypes) => {
  if (!fileName || !allowedTypes || !Array.isArray(allowedTypes)) return false
  
  const extension = fileName.split('.').pop().toLowerCase()
  return allowedTypes.includes(extension)
}

/**
 * 验证必填字段
 * @param {*} value 字段值
 * @returns {boolean}
 */
export const validateRequired = (value) => {
  if (value === null || value === undefined) return false
  if (typeof value === 'string') return value.trim().length > 0
  if (Array.isArray(value)) return value.length > 0
  return true
}

/**
 * 验证字符串长度
 * @param {string} str 字符串
 * @param {number} min 最小长度
 * @param {number} max 最大长度
 * @returns {boolean}
 */
export const validateLength = (str, min, max) => {
  if (!str) return false
  
  const length = String(str).length
  return length >= min && length <= max
}

/**
 * 验证数字范围
 * @param {number} num 数字
 * @param {number} min 最小值
 * @param {number} max 最大值
 * @returns {boolean}
 */
export const validateNumberRange = (num, min, max) => {
  if (num === null || num === undefined) return false
  
  const number = parseFloat(num)
  if (isNaN(number)) return false
  
  return number >= min && number <= max
}

/**
 * 验证日期范围
 * @param {string|Date} date 日期
 * @param {string|Date} minDate 最小日期
 * @param {string|Date} maxDate 最大日期
 * @returns {boolean}
 */
export const validateDateRange = (date, minDate, maxDate) => {
  if (!date) return false
  
  const targetDate = new Date(date)
  if (isNaN(targetDate.getTime())) return false
  
  if (minDate) {
    const min = new Date(minDate)
    if (targetDate < min) return false
  }
  
  if (maxDate) {
    const max = new Date(maxDate)
    if (targetDate > max) return false
  }
  
  return true
}

/**
 * 验证表单数据
 * @param {object} data 表单数据
 * @param {object} rules 验证规则
 * @returns {object} 验证结果
 */
export const validateForm = (data, rules) => {
  const errors = {}
  let isValid = true
  
  for (const field in rules) {
    const value = data[field]
    const fieldRules = rules[field]
    
    for (const rule of fieldRules) {
      const { type, message, ...params } = rule
      
      let fieldValid = true
      
      switch (type) {
        case 'required':
          fieldValid = validateRequired(value)
          break
        case 'phone':
          fieldValid = validatePhone(value)
          break
        case 'email':
          fieldValid = validateEmail(value)
          break
        case 'idCard':
          fieldValid = validateIdCard(value)
          break
        case 'username':
          fieldValid = validateUsername(value)
          break
        case 'password':
          fieldValid = validatePassword(value).isValid
          break
        case 'captcha':
          fieldValid = validateCaptcha(value, params.length)
          break
        case 'smsCode':
          fieldValid = validateSmsCode(value)
          break
        case 'length':
          fieldValid = validateLength(value, params.min, params.max)
          break
        case 'numberRange':
          fieldValid = validateNumberRange(value, params.min, params.max)
          break
        case 'dateRange':
          fieldValid = validateDateRange(value, params.minDate, params.maxDate)
          break
        default:
          fieldValid = true
      }
      
      if (!fieldValid) {
        errors[field] = message || `${field}验证失败`
        isValid = false
        break
      }
    }
  }
  
  return {
    isValid,
    errors
  }
} 